/*
 * @Author: intellectual-seeker 3336339701@qq.com
 * @Date: 2025-09-10 06:38:19
 * @LastEditors: intellectual-seeker 3336339701@qq.com
 * @LastEditTime: 2025-09-10 21:22:44
 * @FilePath: /code/lesson33/cp_ringqueue/RingQueue.hpp
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
#ifndef RING_QUEUE
#define RING_QUEUE
#include <vector>
#include <semaphore.h>
#include <pthread.h>

template<typename T>
class RingQueue
{
private:
    void P(sem_t* sem)
    {
        //sem_post(sem);
        sem_wait(sem);//wait申请
    }

    void V(sem_t* sem)
    {
        //sem_wait(sem);
        sem_post(sem);//post单词译为放入，post操作为释放
    }

    void Lock(pthread_mutex_t* lock)
    {
        pthread_mutex_lock(lock);
    }

    void Unlock(pthread_mutex_t* lock)
    {
        pthread_mutex_unlock(lock);
    }

public:
    RingQueue(int cap)
        :_cap(cap), _ringbuffer(cap), _productor_index(0), _consumer_index(0)
    {
        sem_init(&_room_sem, 0, _cap);//父子进程之间共享pshared: 1, 多线程之间共享pshared: 0
        sem_init(&_data_sem, 0, 0);
        pthread_mutex_init(&_productor_lock, nullptr);
        pthread_mutex_init(&_consumer_lock, nullptr);
    }

    void Enqueue(const T& data)
    {
        P(&_room_sem);
        Lock(&_productor_lock);
        _ringbuffer[_productor_index++] = data;
        _productor_index %= _cap;
        Unlock(&_productor_lock);
        V(&_data_sem);
    }

    void Pop(T* data)
    {
        P(&_data_sem);
        Lock(&_consumer_lock);
        *data = _ringbuffer[_consumer_index++];
        _consumer_index %= _cap;
        Unlock(&_consumer_lock);
        V(&_room_sem);
    }

    ~RingQueue()
    {
        sem_destroy(&_room_sem);
        sem_destroy(&_data_sem);
        pthread_mutex_destroy(&_productor_lock);
        pthread_mutex_destroy(&_consumer_lock);
    }

private:
    vector<T> _ringbuffer;
    int _cap;

    int _productor_index;
    int _consumer_index;

    sem_t _room_sem;
    sem_t _data_sem;

    pthread_mutex_t _productor_lock;
    pthread_mutex_t _consumer_lock;
};

#endif